#ifndef MY_HEADER_H
#define MY_HEADER_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <stdbool.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <pwd.h>
#include <grp.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <signal.h>
#include <pthread.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <shadow.h>
#include <syslog.h>
#include <crypt.h>

//only for this project
#include "train.h"
#include "command.h"
int sends(int sockfd, train_t *train, int type, char filename[]);
int authPasswd(int sockfd);
#define MAX_SIZE 1024
// 检查命令行参数数量是否符合预期
#define ARGS_CHECK(argc, expected) \
    do { \
        if ((argc) != (expected)) { \
            fprintf(stderr, "args num error!\n"); \
            exit(1); \
        } \
    } while (0)

// 检查返回值是否是错误标记,若是则打印msg和错误信息
#define ERROR_CHECK(ret, error_flag, msg) \
    do { \
        if ((ret) == (error_flag)) { \
            perror(msg); \
            exit(1); \
        } \
    } while (0)

//因为thread函数的返回值没有errno，无法用ERROR_CHECK中的perror来输出错误信息
//而是直接返回错误信息int值，因此要重写一个THREAD_ERROR_CHECK函数来判错
//错误信息使用strerror()输出。
//但是，操作系统设计者在后来又给每个子线程附加了errno的副本，因此也可以使用perror输出了。
#define THREAD_ERROR_CHECK(ret, msg) \
    do { \
        if (ret != 0){ \
            fprintf(stderr, "%s:%s", msg, strerror(ret)); \
        } \
    } while (0)

#endif
